package net.maku.im.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import net.maku.framework.common.utils.PageResult;
import net.maku.framework.mybatis.service.impl.BaseServiceImpl;
import net.maku.im.constant.ImConstant;
import net.maku.im.constant.ImRedisKey;
import net.maku.im.convert.ImGroupConvert;
import net.maku.im.dao.ImGroupDao;
import net.maku.im.dto.ImGroupBanDTO;
import net.maku.im.dto.ImGroupQueryDTO;
import net.maku.im.dto.ImGroupUnbanDTO;
import net.maku.im.entity.ImGroupEntity;
import net.maku.im.mq.ImRedisMQTemplate;
import net.maku.im.service.ImGroupMemberService;
import net.maku.im.service.ImGroupService;
import net.maku.im.service.ImUserService;
import net.maku.im.vo.ImGroupVO;
import org.apache.logging.log4j.util.Strings;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * IM群组
 *
 * @author Blue
 * @since 1.0.0 2024-07-14
 */
@Service
@AllArgsConstructor
@DS(ImConstant.DS_IM_PLATFORM)
@CacheConfig(cacheNames = ImRedisKey.IM_CACHE_GROUP)
public class ImGroupServiceImpl extends BaseServiceImpl<ImGroupDao, ImGroupEntity> implements ImGroupService {
    private final ImUserService userService;
    private final ImGroupMemberService groupMemberService;
    private final ImRedisMQTemplate redisMQTemplate;

    @Override
    public List<ImGroupVO> findByName(String name) {
        // 取出用户名或昵称匹配的前10条
        LambdaQueryWrapper<ImGroupEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(StrUtil.isNotEmpty(name), ImGroupEntity::getName, name);
        queryWrapper.select(ImGroupEntity::getId, ImGroupEntity::getName);
        queryWrapper.orderByDesc(ImGroupEntity::getId);
        queryWrapper.last("limit 10");
        List<ImGroupEntity> groups = this.list(queryWrapper);
        return ImGroupConvert.INSTANCE.convertList(groups);
    }

    @Override
    public PageResult<ImGroupVO> page(ImGroupQueryDTO query) {
        LambdaQueryWrapper<ImGroupEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ImGroupEntity::getDissolve, false);
        wrapper.like(StrUtil.isNotEmpty(query.getName()), ImGroupEntity::getName, query.getName());
        wrapper.in(CollectionUtil.isNotEmpty(query.getOwnerIds()), ImGroupEntity::getOwnerId, query.getOwnerIds());
        if (CollectionUtil.isNotEmpty(query.getCreatedTime()) && query.getCreatedTime().size() > 1) {
            wrapper.between(ImGroupEntity::getCreatedTime, query.getCreatedTime().get(0),
                query.getCreatedTime().get(1));
        }
        wrapper.orderByDesc(ImGroupEntity::getId);
        IPage<ImGroupEntity> page = baseMapper.selectPage(getPage(query), wrapper);
        List<ImGroupVO> vos = ImGroupConvert.INSTANCE.convertList(page.getRecords());
        // 填充成员数量
        vos.forEach(vo -> vo.setMemberCount(groupMemberService.findCountByGroupId(vo.getId())));
        return new PageResult<>(vos, page.getTotal());
    }

    @Override
    public ImGroupVO info(Long id) {
        ImGroupEntity group = this.getById(id);
        return ImGroupConvert.INSTANCE.convert(group);
    }

    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = "#dto.getId()")
    @Override
    public void ban(ImGroupBanDTO dto) {
        LambdaUpdateWrapper<ImGroupEntity> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(ImGroupEntity::getId, dto.getId());
        wrapper.set(ImGroupEntity::getIsBanned, true);
        wrapper.set(ImGroupEntity::getReason, dto.getReason());
        this.update(wrapper);
        // 推送到处理队列，等待im-platfrom处理
        redisMQTemplate.opsForList().rightPush(ImRedisKey.IM_QUEUE_GROUP_BANNED, dto);
    }

    @CacheEvict(key = "#dto.getId()")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void unban(ImGroupUnbanDTO dto) {
        LambdaUpdateWrapper<ImGroupEntity> wrapper = Wrappers.lambdaUpdate();
        wrapper.eq(ImGroupEntity::getId, dto.getId());
        wrapper.set(ImGroupEntity::getIsBanned, false);
        wrapper.set(ImGroupEntity::getReason, Strings.EMPTY);
        this.update(wrapper);
        // 推送到处理队列，等待im-platfrom处理
        redisMQTemplate.opsForList().rightPush(ImRedisKey.IM_QUEUE_GROUP_UNBAN, dto);
    }
}